package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.bean.LoginBody;
import com.example.bean.User;
import com.example.common.JwtUtils;
import com.example.domain.DeviceInfo;
import com.example.mapper.DeviceInfoMapper;
import com.example.service.impl.LoginServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/springSecurity")
public class UserController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;
    //addd

  @Autowired
  private LoginServiceImpl loginService;

  @Autowired
  private DeviceInfoMapper deviceInfoMapper;

    // 登录接口，参数为用户名和密码，返回一个包含token的JSON数据
    @PostMapping("/login")
    public String login(@RequestBody LoginBody loginBody) {
        Authentication authentication = null;
        // 使用用户名和密码创建一个UsernamePasswordAuthenticationToken对象，用于认证
        try {
            // 调用AuthenticationManager的authenticate方法进行认证，如果成功，则返回一个包含用户信息和权限信息的Authentication对象
            // 会讲输入的密码进行passwordEncoder.encode("123456")，然后再和数据库中的密码进行比较，只比较加密后的密码，如果匹配成功，则返回一个包含用户信息和权限信息的Authentication对象
             authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword()));
            // 获取用户信息和权限信息，转换为UserDetails对象
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            // 获取用户的角色列表，去掉前缀"ROLE_"
//            List<String> roles = userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).map(role -> role.substring(5)).collect(Collectors.toList());
            List<String> roles = userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());

            // 调用JwtUtils的generateToken方法，根据用户名和角色列表生成token
            String token = jwtUtils.generateToken(userDetails.getUsername(), roles);
            loginService.saveToken(token);
            return "{\"token\": \"" + token + "\"}";
        } catch (Exception e) {
            // 如果认证失败，则抛出异常或返回错误信息
//            throw e;
             return "{\"error\": \"用户名或密码错误\"}";
        }
    }

    // 注销接口，无需参数，返回一个成功信息
    @GetMapping("/logout")
    public String logout() {
        return "";
    }

    // 测试接口，需要ADMIN角色才能访问，返回一个欢迎信息
    @GetMapping("/admin/hello")
   // @PreAuthorize("hasAuthority('system:dev:list')") //方法前权限认证
//    @Secured("admin")
    public String adminHello() {
        return "{\"message\": \"Hello, admin\"}";
    }


    // 测试接口，需要ADMIN角色才能访问，返回一个欢迎信息
    @GetMapping("/admin/hellox")
    @PreAuthorize("hasAnyAuthority('system:dev:list','system:material:list')") //方法前权限认证
//    @Secured("admin")
    public String adminHellox() {
        return "{\"message\": \"Hello, admin\"}";
    }

    @GetMapping("/admin/hello1")
    @PreAuthorize("hasAuthority('system:dev:list11')")
    public String adminHello1() {
        return "{\"message\": \"Hello, admin\"}";
    }

    @GetMapping("/admin/hello2")
    @PreAuthorize("hasPerm('admin')")
    public String adminHello2() {
        return "{\"message\": \"Hello, admin\"}";
    }

    @GetMapping("/admin/hello3")
    @PreAuthorize("hasAuthority('admin123')")
    public String adminHello3() {
        return "{\"message\": \"Hello, admin\"}";
    }



    // 测试接口，需要USER角色才能访问，返回一个欢迎信息
//    @PreAuthorize("hasRole('user')")
    @GetMapping("/user/hello")
    @Secured("ROLE_user") //等同于  @PreAuthorize("hasRole('user')")
    public String userHello() {
        return "{\"message\": \"Hello, user\"}";
    }



    //测试postAuthorize,方法后权限校验
    @GetMapping("/admin/hello4/{id}")
    @PostAuthorize("returnObject%2 == 0")
    public int adminHello4(@PathVariable int id ) {
        return id;
    }

    //PreFilter,方法前过滤
    @DeleteMapping("/admin/hello5/{ids}")
    @PreFilter(filterTarget="ids", value="filterObject%2==0")
    public List<String> adminHello5(@PathVariable List<String> ids) {
        return ids;
    }

    //测试PostFilter,方法后过滤
    @GetMapping("/admin/hello6/{id1}/{id2}/{id3}")
    @PostFilter("filterObject.id % 2 == 0")
    public List<User> adminHello6(@PathVariable int id1, @PathVariable int id2, @PathVariable int id3 ) {
        List<User> resultArrays = new ArrayList<>();
        User user1 = new User();
        user1.setId(id1);
        resultArrays.add(user1);

        User user2 = new User();
        user2.setId(id2);
        resultArrays.add(user2);

        User user3 = new User();
        user3.setId(id3);
        resultArrays.add(user3);

        return resultArrays;

//        return Arrays.asList(id1,id2,id3);
    }


    @GetMapping("/admin/dev/list")
    public List<DeviceInfo> devList( ) {
        LambdaQueryWrapper<DeviceInfo> wrapper = new LambdaQueryWrapper<>();
        List<DeviceInfo> deviceInfos = deviceInfoMapper.selectList(wrapper);
        return deviceInfos;
    }


}

